package com.faklyn.bootredis.controller;

import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Slf4j
@RestController
public class RedisController {

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @GetMapping("testString")
    public Object testString() {
        String key = "boot-redis";
        stringRedisTemplate.opsForValue().set(key, "36", 3, TimeUnit.SECONDS);
        stringRedisTemplate.opsForValue().set("chinese", "容挥霖", 3, TimeUnit.SECONDS);
        Map<String, Object> map = new HashMap<>();
        map.put("key", key);
        map.put("value", stringRedisTemplate.opsForValue().get(key));
        map.put("chinese", stringRedisTemplate.opsForValue().get("chinese"));
        log.info("map: {}", map);
        return map;
    }

    /**
     * 测试url http://localhost:8080/testHash?key=user1&hashKey=height
     *
     * @param key
     * @param hashKey
     * @return
     */
    @GetMapping("testHash")
    public Object testHash(String key, String hashKey) {
        stringRedisTemplate.opsForHash().put("user1", "name", "faklyn");
        stringRedisTemplate.opsForHash().put("user1", "age", "18");
        stringRedisTemplate.opsForHash().put("user1", "height", "176");
//        return stringRedisTemplate.opsForHash().get(key, hashKey);
        return stringRedisTemplate.opsForHash().entries("user1");
    }

    @GetMapping("redisLock")
    public Object restRedisLock(Integer userId) {
        String key = "product1";
        try {
            Boolean lock = stringRedisTemplate.opsForValue().setIfAbsent(key, String.valueOf(userId), 10, TimeUnit.SECONDS);
            if (lock) {
                log.info(userId + "抢到锁了");
                Thread.sleep(5000); // 模拟业务逻辑处理
                // 处理业务逻辑。
                // 有可能出现这样的情况：这里处理业务逻辑时间过长，这个key过期了，业务还没有处理完。这种极端的情况需要开线程检查线程状态，还在处理则不断给key的过期时间续期

                return "恭喜，成功抢到redis锁";
            } else {
                log.info(userId + ", 失败");
                return "不好意思，没有抢到";
            }
        } catch (Exception e) {
            log.error("lock exception");
        } finally {
            // 检查是当前用户加的锁才能删除
            String value = stringRedisTemplate.opsForValue().get(key);
            if (String.valueOf(userId).equals(value)) {
                stringRedisTemplate.delete(key);
            }
        }
        return null;
    }

}
